/*!
 * \file stomp_comm.c
 *
 * \brief stomp解析 共通模块
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * ct管理用共通函数
 *
 * \version 2.0
 * \author geyh
 * \date 2015/10/12
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "frcomm.h"
#include "frmem.h"

#include "stomp_comm.h"

#define  STOMP_MAP_DATA                         1
#define  STOMP_TEXT_DATA                        2
#define  STOMP_BIN_DATA                         3

#define STOMP_DATA_TYPE_BOOL          "java.lang.Boolean"
#define STOMP_DATA_TYPE_CHAR          "java.lang.Character"
#define STOMP_DATA_TYPE_SHORT          "java.lang.Short"
#define STOMP_DATA_TYPE_INT          "java.lang.Integer"
#define STOMP_DATA_TYPE_LONG          "java.lang.Long"
#define STOMP_DATA_TYPE_FLOAT          "java.lang.Float"
#define STOMP_DATA_TYPE_DOUBLE          "java.lang.Double"
#define STOMP_DATA_TYPE_BYTE          "java.lang.Byte"
#define STOMP_JAVA_LANG_NUMBER                     "java.lang.Number"

union int32_float_bits {
    int32_t int_bits;
    float float_bits;
};

union int64_double_bits {
    int64_t int_bits;
    double double_bits;
};


/*!
 * stomp 取得MAP消息的value并上报(string以外)
 *
 * \p_st_body_data    (上报数据链表)
 * \p_st_data         (数据内容)
 * \p_key             (上报字段名)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
FR_STATIC int __stomp_analysis_map_getvalue(Frreport_body_data *p_st_body_data
                                              , Frbyte_Packet *p_st_data
                                              , char *p_key)
{
    char *p_type = NULL;
    uint8_t u8_type_len = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL  || p_key == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 2);

    /* 取得类型的长度 */
    i_ret = bytebuff_get_char(p_st_data, &u8_type_len);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_type = (char *)frmalloc(u8_type_len + 1);
    if (p_type == NULL)
        return FR_FAIL;
    memset(p_type, 0x00, u8_type_len + 1);

    /* 取得类型 */
    i_ret = bytebuff_get_bytes(p_st_data, p_type, u8_type_len);
    if (i_ret == FR_FAIL)
    {
        frfree(p_type);
        return FR_FAIL;
    }

    /* "value"后 */
    bytebuff_skip(p_st_data, 21);

    if (strcmp(p_type, STOMP_DATA_TYPE_BOOL) == 0)
    {
        i_ret = stomp_get_map_boolean(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_CHAR) == 0)
    {
        i_ret = stomp_get_map_char(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_SHORT) == 0)
    {
        i_ret = stomp_get_map_short(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_INT) == 0)
    {
        i_ret = stomp_get_map_int(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_LONG) == 0)
    {
        i_ret = stomp_get_map_long(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_FLOAT) == 0)
    {
        i_ret = stomp_get_map_float(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_DOUBLE) == 0)
    {
        i_ret = stomp_get_map_double(p_st_body_data, p_st_data, p_key);
    }
    else if (strcmp(p_type, STOMP_DATA_TYPE_BYTE) == 0)
    {
        i_ret = stomp_get_map_byte(p_st_body_data, p_st_data, p_key);
    }

    frfree(p_type);

    return i_ret;
}


/*!
 * stomp MAP消息解析
 *
 * \p_st_body_data    (上报数据链表)
 * \p_st_data         (数据内容)
 * \p_key             (上报字段名)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
FR_STATIC int __stomp_analysis_map(Frbyte_Packet *p_st_data
                                     , Frreport_body_data *p_st_body_data
                                     , char *p_key)
{
    char *p_map_key = NULL;
    char *p_map_value = NULL;
    char arr_key[64];
    uint32_t u32_num = 0;
    uint16_t u16_value_len = 0;
    uint16_t u16_key_len = 0;
    uint8_t u8_type = 0;
    int i_num_loop = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL || p_key == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 77);
    /* key-value个数 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_num, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 1);
    for (; (uint32_t)i_num_loop < u32_num; i_num_loop++)
    {
        /* key值长度 */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_key_len, BYTE_BIG_ENDIAN);
        if (i_ret == FR_FAIL)
            goto err;

        p_map_key = (char *)frmalloc(u16_key_len + 1);
        if (p_map_key == NULL)
            goto err;
        memset(p_map_key, 0x00, u16_key_len + 1);

        i_ret = bytebuff_get_bytes(p_st_data, p_map_key, u16_key_len);
        if (i_ret == FR_FAIL)
            goto err;

        /* 判断value类型 */
        i_ret = bytebuff_get_char(p_st_data, &u8_type);
        if (i_ret == FR_FAIL)
            goto err;

        memset(arr_key, 0x00, sizeof(arr_key));
        snprintf(arr_key, sizeof(arr_key), "%s.%s", p_key, p_map_key);

        /* 字符串类型 */
        if (u8_type == '\x74')
        {
            /* value长度 */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_value_len, BYTE_BIG_ENDIAN);
            if (i_ret == FR_FAIL)
                goto err;

            p_map_value = (char *)frmalloc(u16_value_len + 1);
            if (p_map_value == NULL)
                goto err;
            memset(p_map_value, 0x00, u16_value_len + 1);

            /* value值 */
            i_ret = bytebuff_get_bytes(p_st_data, p_map_value, u16_value_len);
            if (i_ret == FR_FAIL)
                goto err;

            /* key-value上报 */
            i_ret = frreport_body_l7_add_str(p_st_body_data, arr_key, p_map_value);
            if (i_ret == FR_FAIL)
                goto err;
            frfree(p_map_value);
            p_map_value = NULL;
        }
        else if (u8_type == '\x75') /* bytes类型 */
        {
            bytebuff_skip(p_st_data, 20);
            /* bytes长度 */
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_value_len, BYTE_BIG_ENDIAN);
            if (i_ret == FR_FAIL)
                goto err;

            p_map_value = (char *)frmalloc(u16_value_len + 1);
            if (p_map_value == NULL)
                goto err;
            memset(p_map_value, 0x00, u16_value_len + 1);

            i_ret = bytebuff_get_bytes(p_st_data, p_map_value, u16_value_len);
            if (i_ret == FR_FAIL)
                goto err;

            /* key-value上报 */
            i_ret = frreport_body_l7_add_bin(p_st_body_data, arr_key, p_map_value, u16_value_len);
            if (i_ret == FR_FAIL)
                goto err;

            frfree(p_map_value);
            p_map_value = NULL;
        }
        else if (u8_type == '\x73') /* 以外 */
        {
            /* 取得value并上报 */
            i_ret = __stomp_analysis_map_getvalue(p_st_body_data, p_st_data, arr_key);
            if (i_ret == FR_FAIL)
                goto err;
        }

        bytebuff_skip(p_st_data, 1);
        frfree(p_map_key);
        p_map_key = NULL;
    }

    return FR_SUCC;

err:
    if (p_map_key)
        frfree(p_map_key);
    if (p_map_value)
        frfree(p_map_value);

    return FR_FAIL;
}

/*!
 * stomp 消息内容上报
 *
 * \p_data_in           (入力参数)
 * \ui_data_len         (数据长度)
 * \p_st_body_data      (上报数据链表)
 * \p_st_private        (私有数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
FR_STATIC int __stomp_message_content(char *p_data_in, unsigned int ui_data_len, Frreport_body_data *p_st_body_data,L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    char arr_key[64];
    Frbyte_Packet *p_st_data = NULL;

    if(p_data_in == NULL || ui_data_len == 0 || p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(p_st_private->i_use_request == FR_NO)
    {
        if(frreport_body_l7_add_int(p_st_body_data, "notify.message.size", 1) == FR_FAIL)
            return FR_FAIL;
    }

    switch (p_st_private->i_mess_type)
    {

        case STOMP_MAP_DATA:
            if(p_st_private->i_use_request)
            {
                if(p_st_private->is_topic)
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "request.mq.topic", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "request.mq.queue", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }

                if(frreport_body_l7_add_str(p_st_body_data, "request.mq.message.type.1", "hashmap") == FR_FAIL)
                    return FR_FAIL;

                if(frreport_body_l7_add_str(p_st_body_data, "request.mq.method", "PUT") == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s", "request.mq.map.1");
            }
            else
            {

                if(p_st_private->is_topic)
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.topic", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.queue", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }

                if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.message.type.1", "hashmap") == FR_FAIL)
                    return FR_FAIL;

                snprintf(arr_key, sizeof(arr_key), "%s", "notify.mq.map.1");

            }
            p_st_data = bytebuff_creat();
            if(p_st_data == NULL)
                return FR_FAIL;

            if(bytebuff_add(p_st_data, p_data_in, ui_data_len) == FR_FAIL)
            {
                bytebuff_free(&p_st_data);
                return FR_FAIL;
            }

            i_ret = __stomp_analysis_map(p_st_data, p_st_body_data, arr_key);
            bytebuff_free(&p_st_data);
            //map message
            break;

        case STOMP_TEXT_DATA:
            if(p_st_private->i_use_request)
            {
                if(p_st_private->is_topic)
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "request.mq.topic", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "request.mq.queue", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }

                if(frreport_body_l7_add_str(p_st_body_data, "request.mq.method", "PUT") == FR_FAIL)
                    return FR_FAIL;

                if(frreport_body_l7_add_str(p_st_body_data, "request.mq.message.type.1", "text") == FR_FAIL)
                    return FR_FAIL;

                i_ret = FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, "request.mq.message.text.1", p_data_in);
            }
            else
            {
                if(p_st_private->is_topic)
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.topic", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.queue", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }


                if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.message.type.1", "text") == FR_FAIL)
                    return FR_FAIL;

                i_ret = FRREPORT_BODY_L7_ADD_STR_LIMIT(p_st_body_data, "notify.mq.message.text.1", p_data_in);

            }
            break;

        case STOMP_BIN_DATA:
            if(p_st_private->i_use_request)
            {
                if(p_st_private->is_topic)
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "request.mq.topic", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "request.mq.queue", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }

                if(frreport_body_l7_add_str(p_st_body_data, "request.mq.message.type.1", "binary") == FR_FAIL)
                    return FR_FAIL;

                if(frreport_body_l7_add_str(p_st_body_data, "request.mq.method", "PUT") == FR_FAIL)
                    return FR_FAIL;

                i_ret = frreport_body_l7_add_bin(p_st_body_data, "request.mq.message.binary.1", p_data_in, ui_data_len);

            }
            else
            {
                if(p_st_private->is_topic)
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.topic", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.queue", p_st_private->p_title) == FR_FAIL)
                        return FR_FAIL;
                }

                if(frreport_body_l7_add_str(p_st_body_data, "notify.mq.message.type.1", "binary") == FR_FAIL)
                    return FR_FAIL;

                i_ret = frreport_body_l7_add_bin(p_st_body_data, "notify.mq.message.binary.1", p_data_in, ui_data_len);


            }
            break;

        default:
            return FR_FAIL;
    }


    return i_ret;

}

/*!
 * 判断单个过程是否结束
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_private        (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
FR_STATIC int __stomp_frame_end(char **pp_data_in, int *p_i_data_len, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    char *p_pos = NULL;
    int i_data_len = 0;
    char *p_data_in = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;

    while(i_data_len)
    {
        //判断是否结束  以 00 0a结尾
        p_pos = (char *)memchr(p_data_in, '\0', i_data_len);
        if(p_pos == NULL)
            return APM_L7_ANALYZE_TODO;

        p_pos++;
        i_data_len -= (p_pos - p_data_in);

        if(i_data_len == 0)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(1);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, "\0", 1);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;
        }

        //00 0a 结尾
        if(*p_pos == '\x0a')
        {
            *pp_data_in = p_pos + 1;
            *p_i_data_len = i_data_len - 1;
            return APM_L7_ANALYZE_SUCC;
        }
    }

    *p_i_data_len = 0;
    return APM_L7_ANALYZE_TODO;
}


/*!
 * connect 命令解析  只获取用户名
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_body_data       (数据上报链表)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
int stomp_connect_parse(char **pp_data_in, int *p_i_data_len, Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    char *p_pos = NULL;
    int i_data_len = 0;
    char *p_value = NULL;
    int i_value_len = 0;
    char *p_data_in = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;
    p_pos = p_data_in;

    while(p_pos && *p_pos != '\0')
    {
        //没取到完整的一行  存到私有数据中继续解析
        p_pos = (char *)memchr(p_data_in, '\x0a', i_data_len);
        if(p_pos == NULL)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(i_data_len);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, p_data_in, (unsigned int)i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;

        }

        if(strncasecmp(p_data_in, "login:", 6) == 0)
        {
            //获取user
            p_data_in += 6;
            i_data_len -= 6;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(p_st_private->p_user_name)
                frfree(p_st_private->p_user_name);

            p_st_private->p_user_name = p_value;
            //指针后移
            i_data_len -= (p_pos + 1 - p_data_in);
            p_data_in = p_pos + 1;
            break;
        }

        i_data_len -= (p_pos + 1 - p_data_in);
        p_data_in = p_pos + 1;
    }


    //判断是否结束  以 00 0a结尾
    i_ret = __stomp_frame_end(&p_data_in, &i_data_len, p_st_private);

    *pp_data_in = p_data_in;
    *p_i_data_len = i_data_len;

    return i_ret;

}

/*!
 * connected 命令解析  只获取server
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_body_data       (数据上报链表)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
int stomp_connected_parse(char **pp_data_in, int *p_i_data_len, Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    int i_data_len = 0;
    char *p_value = NULL, *p_pos = NULL, *p_data_in = NULL;
    int i_value_len = 0;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;
    p_pos = p_data_in;


    while(p_pos && *p_pos != '\0')
    {
        //没取到完整的一行  存到私有数据中继续解析
        p_pos = (char *)memchr(p_data_in, '\x0a', i_data_len);
        if(p_pos == NULL)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(i_data_len);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, p_data_in, (unsigned int)i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;

        }

        if(strncasecmp(p_data_in, "server:", 7) == 0)
        {
            //获取user
            p_data_in += 7;
            i_data_len -= 7;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(p_st_private->p_server)
                frfree(p_st_private->p_server);

            p_st_private->p_server = p_value;
            //指针后移
            i_data_len -= (p_pos + 1 - p_data_in);
            p_data_in = p_pos + 1;
            break;
        }

        i_data_len -= (p_pos + 1 - p_data_in);
        p_data_in = p_pos + 1;
    }


    //判断是否结束  以 00 0a结尾
    i_ret = __stomp_frame_end(&p_data_in, &i_data_len, p_st_private);
    *pp_data_in = p_data_in;
    *p_i_data_len = i_data_len;
    p_st_private->i_flag_data_type = FRLOGIN_SUCC;
    return i_ret;

}

/*!
 * 判断 消息内容 是否结束
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
FR_STATIC int __stomp_message_end(char **pp_data_in, int *p_i_data_len, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    int i_data_len = 0;
    char *p_data_in = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;

    if(p_st_private->i_data_len)
    {
        if(p_st_private->p_str_mess == NULL)
            p_st_private->p_str_mess = frstr_new(i_data_len);

        if(i_data_len >= p_st_private->i_data_len)
        {
            i_ret = frstr_append(p_st_private->p_str_mess, p_data_in, p_st_private->i_data_len);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            p_data_in += p_st_private->i_data_len;
            i_data_len -= p_st_private->i_data_len;

            p_st_private->i_data_len = 0;
        }
        else
        {
            i_ret = frstr_append(p_st_private->p_str_mess, p_data_in, i_data_len);
            if(i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            p_st_private->i_data_len -= i_data_len;
            return APM_L7_ANALYZE_TODO;
        }

    }

    //判断结尾
    i_ret = __stomp_frame_end(&p_data_in, &i_data_len, p_st_private);
    *pp_data_in = p_data_in;
    *p_i_data_len = i_data_len;

    return i_ret;
}

/*!
 * 判断 消息头字段 是否结束
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
FR_STATIC int __stomp_header_end(char **pp_data_in, int *p_i_data_len, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    char *p_pos = NULL;
    char *p_data_in = NULL;
    int i_data_len = 0;

    if(pp_data_in == NULL || p_i_data_len == NULL || *p_i_data_len == 0 || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;

    //第一个字符就是换行符
    if(*p_data_in == '\x0a')
    {
        *pp_data_in = p_data_in + 1;
        *p_i_data_len = i_data_len - 1;
        return APM_L7_ANALYZE_SUCC;
    }

    while(i_data_len)
    {
        //判断是否结束  以  0a结尾
        p_pos = (char *)memchr(p_data_in, '\x0a', i_data_len);
        if(p_pos == NULL)
            return APM_L7_ANALYZE_TODO;

        p_pos++;
        i_data_len -= (p_pos - p_data_in);

        if(i_data_len == 0)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(1);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, "\x0a", 1);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;
        }

        //0a 0a 结尾
        if(*p_pos == '\x0a')
        {
            *pp_data_in = p_pos + 1;
            *p_i_data_len = i_data_len - 1;
            return APM_L7_ANALYZE_SUCC;
        }

        p_data_in = p_pos;
    }

    return APM_L7_ANALYZE_TODO;
}

/*!
 * send 命令解析 获取发送的数据
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_body_data       (数据上报链表)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
int stomp_send_parse(char **pp_data_in, int *p_i_data_len, Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    int i_data_len = 0;
    char *p_value = NULL;
    int i_value_len = 0;
    char *p_mess_content = NULL;
    char *p_data_in = NULL, *p_pos = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;
    p_pos = p_data_in;

    if(p_st_private->p_str_mess)
    {
        i_ret = __stomp_message_end(&p_data_in, &i_data_len, p_st_private);
        if(i_ret == APM_L7_ANALYZE_SUCC)
        {
            //message 获取
            i_value_len = p_st_private->p_str_mess->ui_len;
            p_mess_content = frstr_free2(&p_st_private->p_str_mess);
            if(__stomp_message_content(p_mess_content, i_value_len, p_st_body_data, p_st_private) == FR_FAIL)
            {
                frfree(p_mess_content);
                return APM_L7_ANALYZE_FAIL;
            }
            frfree(p_mess_content);
        }
        *pp_data_in = p_data_in;
        *p_i_data_len = i_data_len;
        return i_ret;
    }

    while(p_pos && *p_pos != '\0')
    {
        if(*p_data_in == '\x0a')
            break;


        //没取到完整的一行  存到私有数据中继续解析
        p_pos = (char *)memchr(p_data_in, '\x0a', i_data_len);
        if(p_pos == NULL)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(i_data_len);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, p_data_in, (unsigned int)i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;

        }

        //读到长度
        if(strncasecmp(p_data_in, "content-length:", 15) == 0)
        {
            //获取长度
            p_data_in += 15;
            i_data_len -= 15;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            p_st_private->i_data_len = atoi(p_value);
            frfree(p_value);
            //指针后移
        }
        else if(strncasecmp(p_data_in, "destination:", 12) == 0)
        {
            //获取user
            p_data_in += 12;
            i_data_len -= 12;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(strncasecmp(p_value, "/topic", 6) == 0)
                p_st_private->is_topic = 1;

            if(p_st_private->p_title)
                frfree(p_st_private->p_title);

            p_st_private->p_title = p_value;
        }
        else if(strncasecmp(p_data_in, "transformation:", 15) == 0)
        {
            //获取user
            p_data_in += 15;
            i_data_len -= 15;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(strcmp(p_value, "MAP") == 0)
                p_st_private->i_mess_type = 1;
            else if(strcmp(p_value, "TEXT") == 0)
                p_st_private->i_mess_type = 2;
            else
                p_st_private->i_mess_type = 3;

            frfree(p_value);
        }

        //指针后移
        i_data_len -= (p_pos + 1 - p_data_in);
        p_data_in = p_pos + 1;

    }


    //消息内容
    i_ret = __stomp_header_end(&p_data_in, &i_data_len, p_st_private);
    if(i_ret == APM_L7_ANALYZE_FAIL || i_ret == APM_L7_ANALYZE_TODO)
        return i_ret;

    // 消息内容处理
    //没有任何数据内容
    if(i_data_len == 0)
    {
        if(p_st_private->p_str_mess)
            p_st_private->p_str_mess = frstr_new(1);

        return APM_L7_ANALYZE_TODO;
    }
    else
    {
        i_ret = __stomp_message_end(&p_data_in, &i_data_len, p_st_private);
        if(i_ret == APM_L7_ANALYZE_SUCC && p_st_private->p_str_mess)
        {
            //message 获取
            i_value_len = p_st_private->p_str_mess->ui_len;
            p_mess_content = frstr_free2(&p_st_private->p_str_mess);
            if(__stomp_message_content(p_mess_content, i_value_len, p_st_body_data, p_st_private) == FR_FAIL)
            {
                frfree(p_mess_content);
                return APM_L7_ANALYZE_FAIL;
            }
            frfree(p_mess_content);
        }
        *pp_data_in = p_data_in;
        *p_i_data_len = i_data_len;
        return i_ret;
    }

}


/*!
 * subscribe 命令解析
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_body_data       (数据上报链表)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
int stomp_subscribe_parse(char **pp_data_in, int *p_i_data_len, Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    int i_data_len = 0;
    char *p_value = NULL;
    int i_value_len = 0;
    char *p_data_in = NULL, *p_pos = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;
    p_pos = p_data_in;

    //receipt-id
    while(p_pos && *p_pos != '\0')
    {
        if(*p_data_in == '\x0a')
            break;

        //没取到完整的一行  存到私有数据中继续解析
        p_pos = (char *)memchr(p_data_in, '\x0a', i_data_len);
        if(p_pos == NULL)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(i_data_len);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, p_data_in, (unsigned int)i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;

        }

        if(strncasecmp(p_data_in, "destination:", 12) == 0)
        {
            //获取destination
            p_data_in += 12;
            i_data_len -= 12;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(strncasecmp(p_value, "/topic", 6) == 0)
                p_st_private->is_topic = 1;

            if(p_st_private->p_title)
                frfree(p_st_private->p_title);

            p_st_private->p_title = p_value;
            break;
            //指针后移
        }

        i_data_len -= (p_pos + 1 - p_data_in);
        p_data_in = p_pos + 1;
    }



    //判断是否结束  以 00 0a结尾
    i_ret = __stomp_frame_end(&p_data_in, &i_data_len, p_st_private);
    *pp_data_in = p_data_in;
    *p_i_data_len = i_data_len;
    return i_ret;

}


/*!
 * message 命令解析  获取推送数据
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_body_data       (数据上报链表)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
int stomp_message_parse(char **pp_data_in, int *p_i_data_len, Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    int i_data_len = 0;
    char *p_value = NULL;
    int i_value_len = 0;
    char *p_mess_content = NULL;
    char *p_data_in = NULL, *p_pos = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;
    p_pos = p_data_in;

    if(p_st_private->p_str_mess)
    {
        i_ret = __stomp_message_end(&p_data_in, &i_data_len, p_st_private);
        if(i_ret == APM_L7_ANALYZE_SUCC)
        {
            //message 获取
            i_value_len = p_st_private->p_str_mess->ui_len;
            p_mess_content = frstr_free2(&p_st_private->p_str_mess);
            if(__stomp_message_content(p_mess_content, i_value_len, p_st_body_data, p_st_private) == FR_FAIL)
            {
                frfree(p_mess_content);
                return APM_L7_ANALYZE_FAIL;
            }
            frfree(p_mess_content);
        }

        *pp_data_in = p_data_in;
        *p_i_data_len = i_data_len;

        return i_ret;
    }

    //content-length:
    while(p_pos && *p_pos != '\0')
    {
        if(*p_data_in == '\x0a')
            break;

        //没取到完整的一行  存到私有数据中继续解析
        p_pos = (char *)memchr(p_data_in, '\x0a', i_data_len);
        if(p_pos == NULL)
        {
            if(p_st_private->p_str_pre)
                frstr_free(&p_st_private->p_str_pre);

            p_st_private->p_str_pre = frstr_new(i_data_len);
            if(p_st_private->p_str_pre == NULL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = frstr_append(p_st_private->p_str_pre, p_data_in, (unsigned int)i_data_len);
            return i_ret == FR_SUCC ? APM_L7_ANALYZE_TODO : APM_L7_ANALYZE_FAIL;

        }

        //读到长度
        if(strncasecmp(p_data_in, "content-length:", 15) == 0)
        {
            //获取长度
            p_data_in += 15;
            i_data_len -= 15;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            p_st_private->i_data_len = atoi(p_value);
            frfree(p_value);
        }
        else if(strncasecmp(p_data_in, "destination:", 12) == 0)
        {
            //获取user
            p_data_in += 12;
            i_data_len -= 12;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(strncasecmp(p_value, "/topic", 6) == 0)
                p_st_private->is_topic = 1;

            if(p_st_private->p_title)
                frfree(p_st_private->p_title);

            p_st_private->p_title = p_value;
            //指针后移

        }
        else if(strncasecmp(p_data_in, "transformation:", 15) == 0)
        {
            //获取user
            p_data_in += 15;
            i_data_len -= 15;
            i_value_len = p_pos - p_data_in + 1;
            p_value = (char *)frmalloc(i_value_len);
            snprintf(p_value, i_value_len, "%s", p_data_in);

            if(strcmp(p_value, "MAP") == 0)
                p_st_private->i_mess_type = 1;
            else if(strcmp(p_value, "TEXT") == 0)
                p_st_private->i_mess_type = 2;
            else
                p_st_private->i_mess_type = 3;

            frfree(p_value);
        }


        //指针后移
        i_data_len -= (p_pos + 1 - p_data_in);
        p_data_in = p_pos + 1;
    }

    i_ret = __stomp_header_end(&p_data_in, &i_data_len, p_st_private);
    if(i_ret == APM_L7_ANALYZE_FAIL || i_ret == APM_L7_ANALYZE_TODO)
        return i_ret;

    // 消息内容处理
    //没有任何数据内容
    if(i_data_len == 0)
    {
        if(p_st_private->p_str_mess)
            p_st_private->p_str_mess = frstr_new(1);

        return APM_L7_ANALYZE_TODO;
    }
    else
    {
        i_ret = __stomp_message_end(&p_data_in, &i_data_len, p_st_private);
        if(i_ret == APM_L7_ANALYZE_SUCC && p_st_private->p_str_mess)
        {
            //message 获取
            i_value_len = p_st_private->p_str_mess->ui_len;
            p_mess_content = frstr_free2(&p_st_private->p_str_mess);
            if(__stomp_message_content(p_mess_content, i_value_len, p_st_body_data, p_st_private) == FR_FAIL)
            {
                frfree(p_mess_content);
                return APM_L7_ANALYZE_FAIL;
            }
            frfree(p_mess_content);
        }

        *pp_data_in = p_data_in;
        *p_i_data_len = i_data_len;
        return i_ret;
    }

}

/*!
 * 其他命令解析  判断是否结束
 *
 * \pp_data_in           (入力参数)
 * \p_i_data_len         (数据长度)
 * \p_st_body_data       (数据上报链表)
 * \p_st_private         (私有数据)
 *
 * \return APM_L7_ANALYZE_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包解析未结束\n
 *         APM_L7_ANALYZE_SUCC:成功
 *
 */
int stomp_others_parse(char **pp_data_in, int *p_i_data_len, Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    int i_data_len = 0;
    char *p_data_in = NULL;

    if(pp_data_in == NULL || *pp_data_in == NULL || p_i_data_len == NULL || p_st_body_data == NULL || p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_data_in = *pp_data_in;
    i_data_len = *p_i_data_len;

    //判断是否结束  以 00 0a结尾
    i_ret = __stomp_frame_end(&p_data_in, &i_data_len, p_st_private);

    *pp_data_in = p_data_in;
    *p_i_data_len = i_data_len;
    return i_ret;

}


/*!
 * 取MAP的boolean型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_boolean(Frreport_body_data *p_st_body_data
                            , Frbyte_Packet *p_st_data
                            , char *p_key)
{
    uint8_t u8_value = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    /* 取boolean值 */
    i_ret = bytebuff_get_char(p_st_data, &u8_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 上报 */
    i_ret = frreport_body_l7_add_int(p_st_body_data, p_key, u8_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * 取MAP的char型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_char(Frreport_body_data *p_st_body_data
                         , Frbyte_Packet *p_st_data
                         , char *p_key)
{
    uint8_t u8_value = 0;
    char arr_str[2];
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 1);
    /* 取char值 */
    i_ret = bytebuff_get_char(p_st_data, &u8_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    snprintf(arr_str, sizeof(arr_str), "%c", u8_value);
    /* 上报 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, p_key, arr_str);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}


/*!
 * 取MAP的short型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_short(Frreport_body_data *p_st_body_data
                          , Frbyte_Packet *p_st_data
                          , char *p_key)
{
    uint16_t u16_value = 0;
    int i_index = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                                        , bytebuff_getPosition(p_st_data)+19
                                        , STOMP_JAVA_LANG_NUMBER, 16, &i_index);
    if (i_ret == FR_SUCC)
        /* 31=18+13 */
        bytebuff_skip(p_st_data, 31);
    else
        bytebuff_skip(p_st_data, 4);

    /* 取short值 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_value, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 上报 */
    i_ret = frreport_body_l7_add_int(p_st_body_data, p_key, u16_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * 取MAP的int型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_int(Frreport_body_data *p_st_body_data
                        , Frbyte_Packet *p_st_data
                        , char *p_key)
{
    uint32_t u32_value = 0;
    int i_index = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                          , bytebuff_getPosition(p_st_data)+19
                          , STOMP_JAVA_LANG_NUMBER, 16, &i_index);
    if (i_ret == FR_SUCC)
        /* 31=18+13 */
        bytebuff_skip(p_st_data, 31);
    else
        bytebuff_skip(p_st_data, 4);

    /* 取int值 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 上报 */
    i_ret = frreport_body_l7_add_int(p_st_body_data, p_key, u32_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}


/*!
 * 取MAP的long型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_long(Frreport_body_data *p_st_body_data
                         , Frbyte_Packet *p_st_data
                         , char *p_key)
{
    uint64_t u64_value = 0;
    int i_index = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                          , bytebuff_getPosition(p_st_data)+19
                          , STOMP_JAVA_LANG_NUMBER, 16, &i_index);
    if (i_ret == FR_SUCC)
        /* 31=18+13 */
        bytebuff_skip(p_st_data, 31);
    else
        bytebuff_skip(p_st_data, 4);

    i_ret = bytebuff_get_long(p_st_data, 8, &u64_value, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    /* 上报 */
    i_ret = frreport_body_l7_add_int(p_st_body_data, p_key, u64_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * 取MAP的float型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_float(Frreport_body_data *p_st_body_data
                          , Frbyte_Packet *p_st_data
                          , char *p_key)
{
    uint32_t u32_value = 0;
    union int32_float_bits u_32bits;
    float f_value = 0.0;
    int i_index = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                          , bytebuff_getPosition(p_st_data)+19
                          , STOMP_JAVA_LANG_NUMBER, 16, &i_index);
    if (i_ret == FR_SUCC)
        /* 31=18+13 */
        bytebuff_skip(p_st_data, 31);
    else
        bytebuff_skip(p_st_data, 4);

    /* 取float值 */
    i_ret = bytebuff_get_int(p_st_data, 4, &u32_value, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    u_32bits.int_bits = u32_value;
    f_value = u_32bits.float_bits;

    /* 上报 */
    i_ret = frreport_body_l7_add_float(p_st_body_data, p_key, f_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}


/*!
 * 取MAP的double型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_double(Frreport_body_data *p_st_body_data
                           , Frbyte_Packet *p_st_data
                           , char *p_key)
{
    uint64_t u64_value = 0;
    double db_value = 0.0;
    union int64_double_bits u_64bits;
    int i_index = 0;
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    i_ret = bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data)
                          , bytebuff_getPosition(p_st_data)+19
                          , STOMP_JAVA_LANG_NUMBER, 16, &i_index);
    if (i_ret == FR_SUCC)
        /* 31=18+13 */
        bytebuff_skip(p_st_data, 31);
    else
        bytebuff_skip(p_st_data, 4);

    i_ret = bytebuff_get_long(p_st_data, 8, &u64_value, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    u_64bits.int_bits = u64_value;
    db_value = u_64bits.double_bits;

    /* 上报 */
    i_ret = frreport_body_l7_add_double(p_st_body_data, p_key, db_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * 取MAP的byte型数据并添加到链表
 *
 * \p_st_body_data(上报链表)
 * \p_st_data(数据)
 * \p_key(上报key)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
int stomp_get_map_byte(Frreport_body_data *p_st_body_data
                         , Frbyte_Packet *p_st_data
                         , char *p_key)
{
    uint8_t u8_value = 0;
    char arr_str[5];
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_data == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 4);
    /* 取byte值 */
    i_ret = bytebuff_get_char(p_st_data, &u8_value);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    snprintf(arr_str, sizeof(arr_str), "%d", u8_value);
    /* 上报 */
    i_ret = frreport_body_l7_add_str(p_st_body_data, p_key, arr_str);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return FR_SUCC;
}
